//this file is part of lMule
//Copyright (C)2002 Tiku
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

// this file will implement GNOME/KDE compatible system tray icon

#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <X11/Xatom.h>

#include "eggtrayicon.h"

#include "SysTray.h"

#include "pixmaps/mule_Tr_grey.ico.xpm"

#define GetRValue(rgb) (((rgb)>>16)&0xff)
#define GetGValue(rgb) (((rgb)>>8)&0xff)
#define GetBValue(rgb) ((rgb)&0xff)

#include <libintl.h>
#include <locale.h>
#include <config.h>
#define _(String) gettext(String)

CSysTray::CSysTray(wxWindow* _parent,int _desktopMode)
{
  gdk_rgb_init();

  /* argH!!! */
  m_sDimensions.cx=16;
  m_sDimensions.cy=16;
  m_nSpacingWidth=1;
  m_nNumBars=1;
  m_nMaxVal=100;
  m_pLimits=NULL;
  m_pColors=NULL;

  parent=_parent;
  desktopMode=_desktopMode;

  if(desktopMode==4) {
    // not wanted, so don't show it.
   return;
  }

  setlocale(LC_ALL, "");
  bindtextdomain(PACKAGE, LOCALEDIR);
  textdomain(PACKAGE);

  bool use_legacy=false;

  // case 2 and 3 are KDE/other legacy system
  if(desktopMode==2 || desktopMode==3) {
    use_legacy=true;
  }

  if(use_legacy) {
    status_docklet=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(status_docklet),_("eMule for Linux"));
    gtk_window_set_wmclass(GTK_WINDOW(status_docklet),"lMule_StatusDocklet","lmule");
    gtk_widget_set_usize(status_docklet,22,22);
  } else {
    status_docklet=GTK_WIDGET(egg_tray_icon_new(_("eMule for Linux")));
    if(status_docklet==NULL) {
      printf("**** WARNING: Can't create status docklet. Systray will not be created.\n");
      desktopMode=4;
      return;
    }
  }
  gtk_widget_realize(status_docklet);

  gtk_signal_connect(GTK_OBJECT(status_docklet),"destroy",
		     GTK_SIGNAL_FUNC(gtk_widget_destroyed),&status_docklet);

  // set image
  GdkBitmap* mask=NULL;
  GdkPixmap* img=gdk_pixmap_create_from_xpm_d(status_docklet->window,&mask,NULL,mule_Tr_grey_ico);

  status_image=gtk_pixmap_new(img,mask);

  // set tooltips
  status_tooltips=gtk_tooltips_new();
  gtk_tooltips_enable(status_tooltips);
  gtk_tooltips_set_tip(status_tooltips,status_docklet,_("eMule for Linux"),"blind text");

  // finalization
  gtk_container_add(GTK_CONTAINER(status_docklet),status_image);
  gtk_signal_connect(GTK_OBJECT(status_image),"destroy",
		     GTK_SIGNAL_FUNC(gtk_widget_destroyed),&status_image);
  gtk_widget_show(status_image);

  if(use_legacy) {
    setupProperties();
  }
  
  gtk_widget_show(status_docklet);
}

void CSysTray::setupProperties()
{
  GdkWindow* window=status_docklet->window;

  glong data[1]; 
  
  GdkAtom kwm_dockwindow_atom;
  GdkAtom kde_net_system_tray_window_for_atom;
  
  kwm_dockwindow_atom = gdk_atom_intern("KWM_DOCKWINDOW", FALSE);
  kde_net_system_tray_window_for_atom = gdk_atom_intern("_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", FALSE);
  
  /* This is the old KDE 1.0 and GNOME 1.2 way... */
  data[0] = TRUE;
  gdk_property_change(window, kwm_dockwindow_atom, 
		      kwm_dockwindow_atom, 32,
		      GDK_PROP_MODE_REPLACE, (guchar *)&data, 1);
  
  /* This is needed to support KDE 2.0 */
  /* can be set to zero or the root win I think */
  data[0] = 0;
  gdk_property_change(window, kde_net_system_tray_window_for_atom, 
		      (GdkAtom)XA_WINDOW, 32,
		      GDK_PROP_MODE_REPLACE, (guchar *)&data, 1);

}

void CSysTray::Show(const wxChar* caption,int nMsgType,DWORD dwTimeToShow,DWORD dwTimeToStay,DWORD dwTimeTOHide)
{
  if(desktopMode==4)
    return;

  if(status_docklet==NULL)
    return;

  /* this isn't exactly true. notifier must be a widget */
  gtk_tooltips_set_tip(status_tooltips,status_docklet,caption,NULL);
}


void CSysTray::TraySetToolTip(char* data)
{
  if(desktopMode==4)
    return;

  if(status_docklet==NULL)
    return;

  gtk_tooltips_set_tip(status_tooltips,status_docklet,data,NULL);
}

COLORREF CSysTray::GetMeterColor(int nLevel)
// it the nLevel is greater than the values defined in m_pLimits the last value in the array is used
{// begin GetMeterColor
	for(int i = 0;i < m_nEntries;i++)
	{
		if(nLevel <= m_pLimits[i])
		{
			return m_pColors[i];
		}
	}
	// default to the last entry
	return m_pColors[m_nEntries-1];
}// end GetMeterColor

void CSysTray::DrawIconMeter(GdkPixmap* pix,GdkBitmap* mask,int nLevel,int nPos)
{
  GdkGC* gc=gdk_gc_new(pix);

  gdk_rgb_gc_set_background(gc,0);
  // border color is black :)
  gdk_rgb_gc_set_foreground(gc,GetMeterColor(nLevel));
  gdk_draw_rectangle(pix,gc,1,((m_sDimensions.cx-1)/m_nNumBars)*nPos+m_nSpacingWidth,m_sDimensions.cy-((nLevel*(m_sDimensions.cy-1)/m_nMaxVal)+1),((m_sDimensions.cx-1)/m_nNumBars)*(nPos+1)+1,m_sDimensions.cy);
  // then draw to mask (look! it must be initialised even if it is not used!)
  GdkGC* newgc=gdk_gc_new(mask);
  gdk_rgb_gc_set_foreground(newgc,0x0);
  gdk_draw_rectangle(mask,newgc,TRUE,0,0,22,22);

  if(nLevel>0) {
    gdk_rgb_gc_set_foreground(newgc,0xffffff);

    gdk_draw_rectangle(mask,newgc,1,m_sDimensions.cx-2,m_sDimensions.cy-((nLevel*(m_sDimensions.cy-1)/m_nMaxVal)+1),
		       m_sDimensions.cx,m_sDimensions.cy);    
  } 
  gdk_gc_unref(newgc);
  gdk_gc_unref(gc);
}

void CSysTray::drawMeters(GdkPixmap* pix,GdkBitmap* mask,int* pBarData)
{
  if(pBarData==NULL)
    return;

  for(int i=0;i<m_nNumBars;i++) {
    DrawIconMeter(pix,mask,pBarData[i],i);
  }
}

void CSysTray::TraySetIcon(char** data,bool what,int* pVals) 
{
  if(desktopMode==4)
    return;

  if(status_image==NULL)
    return; // nothing you can do..

  GdkPixmap* oldpix,*oldbit;
  GdkPixmap* newpix,*newbit;

  /* set new */
  gtk_pixmap_get(GTK_PIXMAP(status_image),&oldpix,&oldbit);
  newpix=gdk_pixmap_create_from_xpm_d(status_docklet->window,&newbit,NULL,data);
  /* create pixmap for meters */
  GdkPixmap *meterpix=gdk_pixmap_new(status_docklet->window,22,22,-1);
  GdkBitmap* meterbit=gdk_pixmap_new(status_docklet->window,22,22,1);
  /* draw meters */
  drawMeters(meterpix,meterbit,pVals);
  /* then draw meters onto main pix */
  GdkGC* mygc=gdk_gc_new(newpix);
  gdk_gc_set_clip_mask(mygc,meterbit);
  gdk_draw_pixmap(newpix,mygc,meterpix,0,0,0,0,22,22);
  gdk_gc_set_clip_mask(mygc,NULL);
  gdk_gc_unref(mygc);
  /* finally combine masks */
  mygc=gdk_gc_new(newbit);
  gdk_gc_set_function(mygc,GDK_OR);
  gdk_draw_pixmap(newbit,mygc,meterbit,0,0,0,0,22,22);
  gdk_gc_unref(mygc);
  gdk_pixmap_unref(meterpix);
  gdk_bitmap_unref(meterbit);
  gtk_pixmap_set(GTK_PIXMAP(status_image),newpix,newbit);
 
  /* free old */
  gdk_pixmap_unref(oldpix);
  gdk_bitmap_unref(oldbit);
  /* and force repaint */
  gtk_widget_draw(status_docklet,NULL);
}

bool CSysTray::SetColorLevels(int *pLimits, COLORREF *pColors,int nEntries)
// pLimits is an array of int that contain the upper limit for the corresponding color
{// begin SetColorLevels
	// free exsisting memory
	if(m_pLimits)
		delete []m_pLimits;
	if(m_pColors)
		delete []m_pColors;
	// allocate new memory
	m_pLimits = new int[nEntries];
	m_pColors = new COLORREF[nEntries];
	// copy values
	for(int i = 0;i < nEntries;i++)
	{// begin copy
		m_pLimits[i] = pLimits[i];
		m_pColors[i] = pColors[i];
	}// end copy
	m_nEntries = nEntries;
	return true;
}// end SetColorLevels
